<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 流年 <liu21st@gmail.com>
// +----------------------------------------------------------------------

// 应用公共文件
use think\facade\Response;

/**
 * dump
 * @author 王崇全
 * @date   2018/9/4 13:25
 * @param $data
 * @return void
 */
function dump($data = null)
{
    header('Content-type: text/plain');
    var_export($data);
    echo "\r\n";
}

/**
 * halt
 * @author 王崇全
 * @date   2018/9/4 13:26
 * @param $data
 * @return void
 */
function halt($data = null)
{
    header('Content-type: text/plain');
    var_export($data);
    die;
}

/**
 * is_mobile
 * @author 王崇全
 * @date
 * @return bool
 */
function is_mobile()
{

    // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
    if (isset ($_SERVER['HTTP_X_WAP_PROFILE'])) {
        return true;
    }
    // 如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
    if (isset ($_SERVER['HTTP_VIA'])) {
        // 找不到为flase,否则为true
        return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false;
    }
    // 脑残法，判断手机发送的客户端标志,兼容性有待提高
    if (isset ($_SERVER['HTTP_USER_AGENT'])) {
        $clientkeywords = [
            'nokia',
            'sony',
            'ericsson',
            'mot',
            'samsung',
            'htc',
            'sgh',
            'lg',
            'sharp',
            'sie-',
            'philips',
            'panasonic',
            'alcatel',
            'lenovo',
            'iphone',
            'ipod',
            'blackberry',
            'meizu',
            'android',
            'netfront',
            'symbian',
            'ucweb',
            'windowsce',
            'palm',
            'operamini',
            'operamobi',
            'openwave',
            'nexusone',
            'cldc',
            'midp',
            'wap',
            'mobile',
        ];
        // 从HTTP_USER_AGENT中查找手机浏览器的关键字
        if (preg_match("/(".implode('|', $clientkeywords).")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) {
            return true;
        }
    }
    // 协议法，因为有可能不准确，放到最后判断
    if (isset ($_SERVER['HTTP_ACCEPT'])) {
        // 如果只支持wml并且不支持html那一定是移动设备
        // 如果支持wml和html但是wml在html之前则是移动设备
        if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'],
                    'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'],
                        'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) {
            return true;
        }
    }

    return false;
}

/**
 * 强制浏览器进行缓存
 * @param int  $expires
 * @param bool $now
 */
function cache_olgt($expires = 20, $now = null)
{
    $now = $now ?? time();
    header("Cache-Control: public");
    header("Pragma: cache");
    header("Last-Modified: ".date('r', $now));
    header("Expires: ".date("r", ($now + $expires)));
    header("Cache-Control: max-age=$expires");

    if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && !empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) + $expires > time())) {
        header("HTTP/1.1 304 Not Modified");
        exit();
    }
}

/**
 * 获取客户端的浏览器信息
 * @author 王崇全
 * @date
 * @param string $ua
 * @return array [名称,版本]
 */
function get_browse(string $ua)
{
    if (stripos($ua, "Firefox/") > 0) {
        preg_match("/Firefox\/([^;)]+)+/i", $ua, $b);
        $exp[0] = "Firefox";
        $exp[1] = $b[1]; //获取火狐浏览器的版本号
    } elseif (stripos($ua, "Maxthon") > 0) {
        preg_match("/Maxthon\/([\d\.]+)/", $ua, $aoyou);
        $exp[0] = "傲游";
        $exp[1] = $aoyou[1];
    } elseif (stripos($ua, "MSIE") > 0) {
        preg_match("/MSIE\s+([^;)]+)+/i", $ua, $ie);
        $exp[0] = "IE";
        $exp[1] = $ie[1]; //获取IE的版本号
    } elseif (stripos($ua, "OPR") > 0) {
        preg_match("/OPR\/([\d\.]+)/", $ua, $opera);
        $exp[0] = "Opera";
        $exp[1] = $opera[1];
    } elseif (stripos($ua, "Edge") > 0) {
        //win10 Edge浏览器 添加了chrome内核标记 在判断Chrome之前匹配
        preg_match("/Edge\/([\d\.]+)/", $ua, $Edge);
        $exp[0] = "Edge";
        $exp[1] = $Edge[1];
    } elseif (stripos($ua, "Chrome") > 0) {
        preg_match("/Chrome\/([\d\.]+)/", $ua, $google);
        $exp[0] = "Chrome";
        $exp[1] = $google[1]; //获取google chrome的版本号
    } elseif (stripos($ua, 'rv:') > 0 && stripos($ua, 'Gecko') > 0) {
        preg_match("/rv:([\d\.]+)/", $ua, $IE);
        $exp[0] = "IE";
        $exp[1] = $IE[1];
    } else {
        $exp[0] = "";
        $exp[1] = "";
    }

    return [
        $exp[0],
        $exp[1],
    ];
}

/**
 * 获取客户端IP
 * @author 王崇全
 * @date
 * @return int ip的整数形式
 */
function get_client_ip()
{
    if (@$_SERVER["HTTP_X_FORWARDED_FOR"]) {
        $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
    } elseif (@$_SERVER["HTTP_CLIENT_IP"]) {
        $ip = $_SERVER["HTTP_CLIENT_IP"];
    } elseif (@$_SERVER["REMOTE_ADDR"]) {
        $ip = $_SERVER["REMOTE_ADDR"];
    } elseif (@getenv("HTTP_X_FORWARDED_FOR")) {
        $ip = getenv("HTTP_X_FORWARDED_FOR");
    } elseif (@getenv("HTTP_CLIENT_IP")) {
        $ip = getenv("HTTP_CLIENT_IP");
    } elseif (@getenv("REMOTE_ADDR")) {
        $ip = getenv("REMOTE_ADDR");
    } else {
        $ip = "Unknown";
    }

    return $ip ? long2ip(ip2long($ip)) : '';
}

/**
 * 获取操作系统类型
 * @author 王崇全
 * @date
 * @param string $agent
 * @return string
 */
function get_plat(string $agent)
{
    if (false !== stripos($agent, 'win') && stripos($agent, '95')) {
        $os = 'Windows 95';
    } elseif (false !== stripos($agent, 'win 9x') && stripos($agent, '4.90')) {
        $os = 'Windows ME';
    } elseif (false !== stripos($agent, 'win') && false !== stripos($agent, '98')) {
        $os = 'Windows 98';
    } elseif (false !== stripos($agent, 'win') && false !== stripos($agent, 'nt 5.0')) {
        $os = 'Windows 2000';
    } elseif (false !== stripos($agent, 'win') && false !== stripos($agent, 'nt 5.1')) {
        $os = 'Windows XP';
    } elseif (false !== stripos($agent, 'win') && false !== stripos($agent, 'nt 5.2')) {
        $os = 'Windows XP';
    } elseif (false !== stripos($agent, 'win') && false !== stripos($agent, 'nt 6.0')) {
        $os = 'Windows Vista';
    } elseif (false !== stripos($agent, 'win') && false !== stripos($agent, 'nt 6.1')) {
        $os = 'Windows 7';
    } elseif (false !== stripos($agent, 'win') && false !== stripos($agent, 'nt 6.2')) {
        $os = 'Windows 8';
    } elseif (false !== stripos($agent, 'win') && false !== stripos($agent, 'nt 6.4')) {
        $os = 'Windows 10';
    } elseif (false !== stripos($agent, 'win') && false !== stripos($agent, 'nt 10')) {
        $os = 'Windows 10';
    } elseif (false !== stripos($agent, 'win') && false !== stripos($agent, 'nt')) {
        $os = 'Windows NT';
    } elseif (false !== stripos($agent, 'win') && false !== stripos($agent, '32')) {
        $os = 'Windows 32';
    } elseif (false !== stripos($agent, 'linux')) {
        $os = 'Linux';
    } elseif (false !== stripos($agent, 'unix')) {
        $os = 'Unix';
    } elseif (false !== stripos($agent, 'sun') && false !== stripos($agent, 'os')) {
        $os = 'SunOS';
    } elseif (false !== stripos($agent, 'ibm') && false !== stripos($agent, 'os')) {
        $os = 'IBM OS/2';
    } elseif (false !== stripos($agent, 'Mac') && false !== stripos($agent, 'PC')) {
        $os = 'Macintosh';
    } elseif (false !== stripos($agent, 'PowerPC')) {
        $os = 'PowerPC';
    } elseif (false !== stripos($agent, 'AIX')) {
        $os = 'AIX';
    } elseif (false !== stripos($agent, 'HPUX')) {
        $os = 'HPUX';
    } elseif (false !== stripos($agent, 'NetBSD')) {
        $os = 'NetBSD';
    } elseif (false !== stripos($agent, 'BSD')) {
        $os = 'BSD';
    } elseif (false !== stripos($agent, 'OSF1')) {
        $os = 'OSF1';
    } elseif (false !== stripos($agent, 'IRIX')) {
        $os = 'IRIX';
    } elseif (false !== stripos($agent, 'FreeBSD')) {
        $os = 'FreeBSD';
    } elseif (false !== stripos($agent, 'teleport')) {
        $os = 'teleport';
    } elseif (false !== stripos($agent, 'flashget')) {
        $os = 'flashget';
    } elseif (false !== stripos($agent, 'webzip')) {
        $os = 'webzip';
    } elseif (false !== stripos($agent, 'offline')) {
        $os = 'offline';
    } else {
        $os = '';
    }

    return $os;
}

/**
 * 生成UUID
 * @author 王崇全
 * @date
 * @return string
 */
function uuid()
{
    if (function_exists('com_create_guid')) {
        return com_create_guid();
    } else {
        mt_srand((double)microtime() * 10000);//optional for php 4.2.0 and up.
        $charid = strtoupper(md5(uniqid(rand(), true)));
        //$hyphen = chr(45);// "-"
        $hyphen = "";// "-"
        $uuid   = substr($charid, 0, 8).$hyphen.substr($charid, 8, 4).$hyphen.substr($charid, 12,
                4).$hyphen.substr($charid, 16, 4).$hyphen.substr($charid, 20, 12);

        return strtolower($uuid);
    }
}

/**
 * 毫秒时间戳
 * @author 王崇全
 * @date
 * @return array|string
 */
function mtime()
{
    $time  = explode(" ", microtime());
    $time  = $time [1].($time [0] * 1000);
    $time2 = explode(".", $time);
    $time  = $time2 [0];

    return $time;
}

/**
 * 返回json格式
 * @author 王崇全
 * @date
 * @param int    $code 错误码
 * @param string $msg  信息
 * @param array  $data 数据
 * @return void
 */
function rj($code = 0, $msg = "操作成功", $data = [])
{
    json([
        "code" => $code ?? 0,
        "msg"  => $msg ?? "",
        "data" => $data,
    ], 200, [])->send();
    exit;
}

/**
 * 返回json数据
 * @author 王崇全
 * @date
 * @param array $data 数据
 * @return void
 */
function rjd($data = [])
{
    json([
        "code" => 0,
        "msg"  => "",
        "data" => $data,
    ], 200, [])->send();
    exit;
}

/**
 * 远程日志
 * @author 王崇全
 * @date   2018/11/1 17:49
 * @param string $log   log信息 支持字符串和数组
 * @param string $level 日志级别
 * @return void
 */
function L($log = '这是个标记', $level = 'dump')
{
    trace($log, $level);
}

/**
 * 遍历获取某路径下的文件,包括子文件夹
 * @author 王崇全
 * @param string $dir 目录名
 * @return array|null 包含完整文件路径级文件名的数组
 */
function get_files($dir)
{
    //如果本身就是个文件,直接返回
    if (is_file($dir)) {
        return [$dir];
    }
    //创建数组,存储文件名
    $files = [];

    if (is_dir($dir) && ($dir_p = opendir($dir))) {//路径合法且能访问//创建目录句柄
        $ds = '/';  //目录分隔符
        while (($filename = readdir($dir_p)) !== false) {  //返回打开目录句柄中的一个条目
            if ($filename == '.' || $filename == '..') {
                continue;
            }  //排除干扰项
            $filetype = filetype($dir.$ds.$filename);  //获取本条目的类型(文件或文件夹)
            if ($filetype == 'dir') {  //如果收文件夹,
                $files = array_merge($files, get_files($dir.$ds.$filename));  //进行递归,并将结果合并到数组中
            } elseif ($filetype == 'file') {  //如果是文件,
                $files[] = mb_convert_encoding($dir.$ds.$filename, 'UTF-8', 'GBK');  //将文件名转成utf-8后存到数组
            }
        }
        closedir($dir_p);  //关闭目录句柄
    } else {//非法路径
        $files = null;
    }

    return $files;
}

/**
 * 从文件中读取内容， 不能超过2M
 * @param  string $file   文件
 * @param int     $offset 起始位置 默认，开头
 * @param int     $length 长度 不能超过2M， 默认2M
 * @return bool|string
 */
function get_from_file($file, $offset = 0, $length = 0)
{
    if (!is_file($file)) {
        return false;
    }

    //打开文件
    if (!$f = fopen($file, 'rb')) {
        return false;
    }

    //指针偏移
    if ($offset < 0) {
        fseek($f, $offset, SEEK_END);
    } else {
        fseek($f, $offset);
    }

    //长度

    if ($length > 1024 * 1024 * 2) {
        return false;
    } elseif ($length == 0) {
        $length = 1024 * 1024 * 2;
    }

    return @fread($f, $length);
}

/**
 * 删除文件夹及其内部文件
 * @param string $dir 文件夹路径
 * @return bool
 */
function dir_del($dir)
{
    if (!is_dir($dir)) {
        return false;
    }

    //先删除目录下的文件：
    $dh = opendir($dir);
    while ($file = readdir($dh)) {
        if ($file != "." && $file != "..") {
            $fullpath = $dir."/".$file;
            if (!is_dir($fullpath)) {
                @unlink($fullpath);
            } else {
                dir_del($fullpath);
            }
        }
    }
    closedir($dh);

    //删除当前文件夹：
    if (!@rmdir($dir)) {
        return false;
    }

    return true;
}

/**
 * 生成器处理数组
 * @author 王崇全
 * @date
 * @param array $data
 * @return Generator
 */
function arrYield(array $data)
{
    foreach ($data as $k => $v) {
        yield $k => $v;
    }
}

/**
 * redis_set
 * @author 王崇全
 * @date
 * @param Redis  $rd
 * @param string $key
 * @param mixed  $value
 * @param int    $timeOut
 * @return bool TRUE if the command is successful.
 */
function redis_set(\Redis $rd, string $key, $value)
{
    $key = strtolower($key);

    if (is_array($value)) {
        $value = json_encode($value, JSON_UNESCAPED_UNICODE);
    } elseif (is_object($value)) {
        $value = json_encode($value, JSON_FORCE_OBJECT);
    }

    return $rd->set($key, $value);
}

/**
 * redis_get
 * @author 王崇全
 * @date
 * @param Redis  $rd
 * @param string $key
 * @return bool|mixed|null|string
 */
function redis_get(Redis $rd, string $key)
{
    $value = $rd->get($key);
    if ($value === false) {
        return null;
    }

    $v = json_decode($value, true);
    if (is_null($v)) {
        return $value;
    }

    return $v;
}

/**
 * send_http
 * @author 王崇全
 * @date
 * @param string $url
 * @param array  $data
 * @param array  $header
 * @return mixed
 * @throws Exception
 */
function send_http(string $url, array $data = [], array $header = [])
{


    $ch = curl_init();

    if ($data) {
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
    }

    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);//单位S 秒

    $res = curl_exec($ch);

    curl_getinfo($ch);

    if (curl_error($ch)) {
        throw new Exception("curl_http_error:".curl_error($ch));
    }

    return $res;
}

/**
 * 导出订单
 * @author wanglin
 * @param array  $headings
 * @param array  $rows
 * @param string $file_name
 * @return bool|string
 */
function export_csv($headings = [], $rows = [], $file_name = '')
{
    if ((!empty($headings)) && (!empty($rows))) {
        $file_name = $file_name !== '' ? $file_name : 'export';
        $name      = $file_name.'_'.date('YmdHis').'.csv'; //构造文件名
        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename='.$name);
        $output = fopen("../public/".$name, 'w');
        array_unshift($rows, $headings); //写入表头
        foreach ($rows as $row) { //逐行写入
            $converted = array_map(function ($item)
            {
                return iconv('UTF-8', 'GBK', $item);
            }, $row);
            fputcsv($output, $converted);
        }

        return IMG_URL.'/'.$name;
    }

    return false;
}

/**
 * 获取图片的Base64编码(不支持url)
 * @param string $img_file 传入本地图片地址
 * @author wang
 * @return string
 */
function img_to_base64($img_file)
{

    $img_base64 = '';
    if (file_exists($img_file)) {
        $app_img_file = $img_file; // 图片路径
        $img_info     = getimagesize($app_img_file); // 取得图片的大小，类型等

        $fp = fopen($app_img_file, "r"); // 图片是否可读权限

        if ($fp) {
            $filesize     = filesize($app_img_file);
            $content      = fread($fp, $filesize);
            $file_content = chunk_split(base64_encode($content)); // base64编码
            switch ($img_info[2]) {           //判读图片类型
                case 1:
                    $img_type = "gif";
                    break;
                case 2:
                    $img_type = "jpg";
                    break;
                case 3:
                    $img_type = "png";
                    break;
            }

            $img_base64 = 'data:image/'.$img_type.';base64,'.$file_content;//合成图片的base64编码

        }
        fclose($fp);
    }

    return $img_base64; //返回图片的base64
}

/**
 * 生成密码
 * @author 王崇全
 * @date   2018/11/7 16:35
 * @param int $length
 * @return string
 */
function mk_pwd(int $length = 16)
: string {
    // 密码字符集，可任意添加你需要的字符
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789^&*()-_ []{}<>~+';

    $password = '';
    for ($i = 0; $i < $length; $i++) {
        // 取字符数组 $chars 的任意元素
        $password .= $chars[mt_rand(0, strlen($chars) - 1)];
    }

    return $password;
}

function s2b($str)
{
    //1.列出每个字符
    $arr = preg_split('/(?<!^)(?!$)/u', $str);
    //2.unpack字符
    foreach ($arr as &$v) {
        $temp = unpack('H*', $v);
        $v    = base_convert($temp[1], 16, 2);
        unset($temp);
    }

    return join(' ', $arr);
}

function b2s($str)
{
    $arr = explode(' ', $str);
    foreach ($arr as &$v) {
        $v = pack("H".strlen(base_convert($v, 2, 16)), base_convert($v, 2, 16));
    }

    return join('', $arr);
}

/**
 * 生成订单编号
 * @author whd
 * @date
 * @return string
 */
function makeOrderNo()
{
    return date("YmdHis").uniqid();
}

/**
 * 生成唯一邀请码
 * @author 王海东
 * @date
 * @param int $lenth    邀请码长度
 * @return string
 */
function create_invite_code(int $lenth = 4)
: string {
    $code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $rand = $code[rand(0,25)]
        .strtoupper(dechex(date('m')))
        .date('d')
        .substr(time(),-5)
        .substr(microtime(),2,5)
        .sprintf('%02d',rand(0,99));
    for(
        $a = md5( $rand, true ),
        $s = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
        $d = '',
        $f = 0;
        $f < $lenth;
        $g = ord( $a[ $f ] ),
        $d .= $s[ ( $g ^ ord( $a[ $f + 8 ] ) ) - $g & 0x1F ],
        $f++
    );
    return $d;
}


